package controllers;

import answer_factory.IAnswerFactory;
import answer_factory.MulitpleChoiceAnswerFactory;
import answer_factory.ShortAnswerFactory;
import answer_factory.TrueFalseAnswerFactory;
import answers.IAnswer;
import answers.Response;
import question_factory.IQuestionFactory;
import question_factory.MultipleChoiceQuestionFactory;
import question_factory.ShortQuestionFactory;
import question_factory.TrueFalseQuestionFactory;
import main.ConsoleInterpreterSingleton;
import models.AbstractQuestion;
import models.SurveyModel;
import mvc.AbstractView;
import mvc.IController;

public class SurveyController implements IController
{

	public SurveyController(SurveyModel model)
	{
		itsSurveyModel = model;
	}
	
	@Override
	public void onAction(String encoding)
	{
		if(itsSurveyModel.getEditMode() == true)
		{
			onEditSurveyAction(encoding);
		}
		else
		{
			onTakeSurveyAction(encoding);
		}
	}

	private void onEditSurveyAction(String encoding)
	{
		String [] tokens = encoding.split("\\s");
		
		String command = tokens[0];
		if(command.equals("addQuestion"))
		{
			AbstractQuestion question = createQuestionFromEncoding(encoding);
			if(question != null)
			{
				itsSurveyModel.addQuestion(question);
			}
			else
			{
				System.out.println("Wrong question format");
			}
		}
		else if(command.equals("deleteQuestion"))
		{
			try
			{
				int position = Integer.parseInt(tokens[1]);
				itsSurveyModel.deleteQuestion(position);
			}
			catch(NumberFormatException e)
			{
				System.out.println("Wrong question position, this survey has " + itsSurveyModel.size() + " questions");
			}
		}
		else if(command.equals("viewQuestion"))
		{
			try
			{
				int position = Integer.parseInt(tokens[1]);
				itsSurveyModel.viewQuestion(position);
			}
			catch(NumberFormatException e)
			{
				System.out.println("Wrong question position, this survey has " + itsSurveyModel.size() + " questions");
			}
		}
		else if(command.equals("viewSurvey"))
		{
			itsSurveyModel.viewSurvey();
		}
		else if(command.equals("editQuestion"))
		{
			String s = encoding.substring(13);
			s = s.trim();
			int spaceIdx = s.indexOf(' ', 0);
			String positionStr = s.substring(0, spaceIdx);
			try
			{
				int questionPosition = Integer.parseInt(positionStr);
				AbstractQuestion question = createQuestionFromEncoding(s);
				if(question != null)
				{
					itsSurveyModel.editQuestion(questionPosition, question);
				}
				else
				{
					System.out.println("Wrong question format");
				}
			}
			catch(NumberFormatException e)
			{
				System.out.println("Wrong question position, this survey has " + itsSurveyModel.size() + " questions");
			} 
		}
		else if(command.equals("saveAndExit"))
		{
			AbstractView view = itsSurveyModel.getControllerMonitorView();
			ConsoleInterpreterSingleton interpreter = ConsoleInterpreterSingleton.getInstance();
			interpreter.pipeEventsTo(view);
			SurveyModel.save(itsSurveyModel);
			System.out.println("end edit survey\n");
				
		}
		else if(command.equals("?"))
		{
			System.out.println("Usage:");
			System.out.println("addQuestion truefalse [points] [question text] -a [answer] : add a true false question, [answer]=0/1 for false/true respectively");
			System.out.println("addQuestion xchoice [points] [question text] [(option1, option 2, ...)] -a [(selction1, selection2...)] : \nadd a multiple choice question");
			System.out.println("addQuestion short [points] [question text] -a [answer] : add a short question");
			System.out.println("deleteQuestion [i] : delete a question at position i, all otehr questions will be repositioned");
			System.out.println("viewQuestion [i] : view a question at position i");
			System.out.println("viewSurvey : view all the questions in this survey");
			System.out.println("editQuestion [i] [all other arguments as defines in the 'addQuestion' command] : edit a question at position i");
			System.out.println("saveAndExit : save and exit editing the survey (this will take you back to the desktop)");
		}
		else
		{
			System.out.println("Uknown command, type '?' for help");
		}
	}
	
	
	private void onTakeSurveyAction(String encoding)
	{
		String [] tokens = encoding.split("\\s");
		
		if(tokens[0].equals("?"))
		{
			System.out.println("Answering a survey:");
			System.out.println("answer [question number] [answer text], where 'answer text' is:");
			System.out.println("* <0 or 1> for for short questions ");
			System.out.println("* <some text> for true false question (false\true) ");
			System.out.println("* <list of choices> for multiple choice question, e.g. (bla,x) ");
			return;
		}
		else if(!tokens[0].equals("answer"))
		{
			System.out.println("Illegal answer format, please try again");
			return;
		}
		
		Response response = createResponseFromEncoding(encoding);
		if(response != null)
		{
			itsSurveyModel.respond(response);
		}
		else
		{
			System.out.println("Wrong answer format!");
		}	
	}
	
	private AbstractQuestion createQuestionFromEncoding(String encoding)
	{
		AbstractQuestion question = null;
		IQuestionFactory factory = null;
		
		String [] tokens = encoding.split("\\s");
		String questionType = tokens[1];
		
		if(questionType.equals("truefalse"))
		{
			factory = new TrueFalseQuestionFactory();
		}
		else if(questionType.equals("xchoice"))
		{
			factory = new MultipleChoiceQuestionFactory();
		}
		else if(questionType.equals("short"))
		{
			factory = new ShortQuestionFactory();
		}
		
		if(factory != null)
		{
			question = factory.createQuestion(encoding);
		}
		return question;
	}
	
	private Response createResponseFromEncoding(String encoding)
	{
		IAnswerFactory factory = null;
		Response response = new Response();
		int position = -1;
		try
		{
			String [] tokens = encoding.split("\\s");
			position = Integer.parseInt(tokens[1]);
		}
		catch(NumberFormatException e)
		{
			return null;
		}
		
		if(enforceOrder(position) == false)
		{
			System.out.println("Please place your answers in their correct order!");
			return null;
		}
		
		if(position > itsSurveyModel.size() || position < 1)
		{
			return null;
		}
		AbstractQuestion question = itsSurveyModel.getAbstractQuestion(position);
		response.setPoints(question.getPoints());
		if(question == null)
		{
			return null;
		}
		String category = question.getCategory();
		if(category.equals("True-false question"))
		{
			factory = new TrueFalseAnswerFactory();
		}
		else if(category.equals("Multiple choice question"))
		{
			factory = new MulitpleChoiceAnswerFactory();
		}
		else if(category.equals("short question"))
		{
			factory = new ShortAnswerFactory();
		}
		else
		{
			return null;
		}
		
		IAnswer answer = factory.createAnswer(encoding);
		response.setItsIAnswer(answer);
		response.setQuestionPosition(position);
		response.setScore(0);
		
		return response;
	}
	
	
	private boolean enforceOrder(int position)
	{
		int lastAnswered = itsSurveyModel.getLastResponsePosition();
		if(position != lastAnswered + 1)
		{
			return false;
		}
		else
		{
			return true;
		}
	}
	private SurveyModel itsSurveyModel;
}
